package communication.definitions;

import communication.exceptions.InvalidArgumentsException;
import communication.exceptions.InvalidFunctionException;

/**
 * The enumerated type representing functions which can be received by and
 * executed on the client.
 * 
 * @author Peter Kalauskas
 */
public enum ReceivedFunction implements Function {
	// Sensor
	SET_VALUE(ARRAY);

	private int args;

	/**
	 * Constructor for the a <code>ReceivedFunction</code>
	 * 
	 * @param args
	 *            the number of arguments this function expects.
	 */
	ReceivedFunction(int args) {
		this.args = args;
	}

	/**
	 * Returns the number of expected arguments.
	 * 
	 * @return the number of expected arguments.
	 */
	public int arguments() {
		return args;
	}

	/**
	 * Returns a byte for this ReceivedFunction.
	 *  
	 * @return the byte corresponding to this ReceivedFunction
	 */
	public byte byteValue() {
		return (byte) ordinal();
	}

	/**
	 * Returns a ReceivedFunction for this byte.
	 * 
	 * @param b
	 *            the byte for which a ReceivedFunction will be found
	 * @return the ReceivedFunction corresponding to this byte
	 * @throws InvalidFunctionException
	 */
	public static ReceivedFunction valueOf(byte b)
			throws InvalidFunctionException {
		// Convert the byte to an unsigned int and return the ReceivedFunction
		// found in the corresponding array of DeviceTypes
		try {
			return ReceivedFunction.values()[b & 0xFF];
		} catch (IndexOutOfBoundsException e) {
			throw new InvalidFunctionException("ReceivedFunction ID "
					+ (b & 0xFF) + " does not exist.");
		}
	}

	/**
	 * Checks if the size of the argument array agrees with the expected
	 * arguments defined by the Function.
	 * 
	 * @param args
	 *            the arguments to be size checked.
	 * @throws InvalidArgumentsException
	 *             if data.length is greater than or less than the number of
	 *             arguments the <code>ReceivedFunction</code> expected. This
	 *             will never be thrown if the function expects an array.
	 */
	public void checkArguments(byte args[]) throws InvalidArgumentsException {
		if (arguments() != ARRAY) {
			if (arguments() > args.length) {
				throw new InvalidArgumentsException(
						"Too few arguements given to function " + this);
			} else if (arguments() < args.length) {
				throw new InvalidArgumentsException(
						"Too many arguements given to function " + this);
			}
		}
	}
}
